package hell.satan.droidbdf.fragment;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Message;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.TextView;

import hell.satan.droidbdf.R;
import hell.satan.droidbdf.base.BaseFragment;
import hell.satan.droidbdf.utils.Constants;
import hell.satan.droidbdf.utils.LogWrapper;

/**
 * 对WebView进行包装的Fragement
 * Fragement wrapper for WebView
 *
 * @author Cerberus
 */
@SuppressWarnings("unused")
public class BrowserFragment extends BaseFragment implements View.OnClickListener {
    protected static final int MSG_ID_LOAD_URL = GENERATOR.generateID("msg");
    protected static final long INTERVAL_LOAD_URL = 100;

    protected ViewGroup mError;
    protected TextView mMessage;

    protected ProgressBar mProgress;
    protected WebView mBrowser;

    public static BrowserFragment newInstance() {
        return newInstance("");
    }

    public static BrowserFragment newInstance(String url) {
        Bundle bundle = new Bundle();
        bundle.putString(Constants.EXTRA_FRAGMENT_URL, url);
        return newInstance(bundle);
    }

    public static BrowserFragment newInstance(Bundle args) {
        BrowserFragment fragment = new BrowserFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(@Nullable final Bundle state) {
        super.onCreate(state);
        Bundle extra = getArguments();
        if (extra != null) {
            loadUrl(extra.getString(Constants.EXTRA_FRAGMENT_URL));
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle state) {
        return inflater.inflate(R.layout.fragment_browser, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle state) {
        super.onViewCreated(view, state);

        mError = (ViewGroup) view.findViewById(R.id.error);
        mError.setOnClickListener(this);
        mMessage = (TextView) view.findViewById(R.id.message);

        mProgress = (ProgressBar) view.findViewById(R.id.progress);

        mBrowser = (WebView) view.findViewById(R.id.browser);
        onWebViewSettings(mBrowser.getSettings());
        BrowserViewClient vc = onCreateViewClient();
        vc.setFragment(this);
        mBrowser.setWebViewClient(vc);
        BrowserChromeClient cc = onCreateChromeClient();
        cc.setFragment(this);
        mBrowser.setWebChromeClient(cc);
    }

    @Override
    public void onResume() {
        super.onResume();
        mBrowser.onResume();
        mBrowser.resumeTimers();
    }

    @Override
    public void onPause() {
        mBrowser.pauseTimers();
        mBrowser.onPause();
        super.onPause();
    }

    @Override
    public void onDestroyView() {
        mBrowser.destroy();
        super.onDestroyView();
    }

    @Override
    protected void handleMessage(Message msg) {
        int what = msg.what;
        if (what == MSG_ID_LOAD_URL) {
            removeMessages(what);
            if (mBrowser != null) {
                mBrowser.loadUrl((String) msg.obj);
            } else {
                Message message = Message.obtain(msg);
                sendMessageDelayed(message, INTERVAL_LOAD_URL);
            }
        } else {
            super.handleMessage(msg);
        }
    }

    @CallSuper
    @Override
    public void onClick(View view) {
        int id = view.getId();
        if (id == R.id.error) {
            mBrowser.setVisibility(View.VISIBLE);
            mError.setVisibility(View.INVISIBLE);
            mBrowser.reload();
        }
    }

    /**
     * 设置WebView
     * Setting WebView
     *
     * @param settings WebView设置对象
     *                 the WebSettings object used to control the settings for WebView
     */
    @SuppressLint("SetJavaScriptEnabled")
    protected void onWebViewSettings(@NonNull WebSettings settings) {
        settings.setJavaScriptEnabled(true);
    }

    /** @see WebView#reload() */
    public void reload() {
        if (mBrowser != null) mBrowser.reload();
    }

    /** @see WebView#canGoBack() */
    public boolean canGoBack() {
        return mBrowser != null && mBrowser.canGoBack();
    }

    /** @see WebView#goBack() */
    public void goBack() {
        if (mBrowser != null) mBrowser.goBack();
    }

    /** @see WebView#canGoForward() */
    public boolean canGoForward() {
        return mBrowser != null && mBrowser.canGoForward();
    }

    /** @see WebView#goForward() */
    public void goForward() {
        if (mBrowser != null) mBrowser.goForward();
    }

    /** @see WebView#canGoBackOrForward(int) */
    public boolean canGoBackOrForward(int steps) {
        return mBrowser != null && mBrowser.canGoBackOrForward(steps);
    }

    /** @see WebView#goBackOrForward(int) */
    public void goBackOrForward(int steps) {
        if (mBrowser != null) mBrowser.goBackOrForward(steps);
    }

    /** @see WebView#loadUrl(String) */
    public void loadUrl(String url) {
        if (!TextUtils.isEmpty(url)) {
            Message message = Message.obtain();
            message.what = MSG_ID_LOAD_URL;
            message.obj = url;
            sendMessage(message);
        }
    }

    @NonNull
    protected BrowserViewClient onCreateViewClient() {
        return new BrowserViewClient();
    }

    @NonNull
    protected BrowserChromeClient onCreateChromeClient() {
        return new BrowserChromeClient();
    }

    protected static class BrowserViewClient extends WebViewClient {
        private BrowserFragment mFragment;

        private void setFragment(BrowserFragment fragment) {
            mFragment = fragment;
        }

        public BrowserFragment getFragment() {
            return mFragment;
        }

        @CallSuper
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return false;
        }

        @CallSuper
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            mFragment.mProgress.setVisibility(View.VISIBLE);
        }

        @CallSuper
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            mFragment.mProgress.setVisibility(View.INVISIBLE);
        }

        @CallSuper
        @Override
        @SuppressWarnings("deprecation")
        public void onReceivedError(WebView view, int code, String description, String url) {
            LogWrapper.d(mFragment.TAG, "%1$s(%2$s:%3$s)", url, description, code);
            mFragment.mMessage.setText(description);
            mFragment.mBrowser.setVisibility(View.INVISIBLE);
            mFragment.mError.setVisibility(View.VISIBLE);
        }
    }

    protected static class BrowserChromeClient extends WebChromeClient {
        private BrowserFragment mFragment;

        private void setFragment(BrowserFragment fragment) {
            mFragment = fragment;
        }

        public BrowserFragment getFragment() {
            return mFragment;
        }

        @CallSuper
        @Override
        public void onProgressChanged(WebView view, int progress) {
            mFragment.mProgress.setProgress(progress);
        }

        @Override
        @SuppressWarnings("deprecation")
        public void onConsoleMessage(String message, int line, String sourceID) {
            LogWrapper.d(mFragment.TAG, "%1$s(%2$s:%3$s)", message, sourceID, line);
        }
    }
}
